package wsdc.app.main.v2;

// PKCSCertificateManager.java
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import wsdc.app.main.SpringContext;
import wsdc.app.main.v1.CertApi;

import javax.net.ssl.SSLException;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * PKCS证书管理器，负责动态加载和缓存PKCS格式的SSL证书
 */
public class PKCSCertificateManager {
    
    // 证书存储路径
    private final String certificatePath;
    
    // SSL上下文缓存
    private final ConcurrentMap<String, SslContext> sslContextCache = new ConcurrentHashMap<>();

    // 密钥库密码
    private String keystorePassword = "certpass123";
    
    public PKCSCertificateManager(String certificatePath) {
        this.certificatePath = certificatePath;
    }
    CertApi certApi;
    {
        SpringContext.register(c -> {
            certApi = c.getBean(CertApi.class);
        });
    }
    /**
     * 根据主机名加载SSL上下文
     * 
     * @param hostname 主机名
     * @return SSL上下文
     * @throws SSLException 证书加载失败时抛出
     */
    public synchronized SslContext  loadSslContext(String hostname) throws SSLException {
        // 首先检查缓存
        SslContext cachedContext = sslContextCache.get(hostname);
        if (cachedContext != null) {
            return cachedContext;
        }
        
        // 缓存未命中，加载证书文件
        try {
            SslContext sslContext = loadCertificateFromFile(hostname);
            
            // 缓存SSL上下文
            SslContext previous = sslContextCache.putIfAbsent(hostname, sslContext);
            if (previous != null) {

                return previous;
            }
            
            return sslContext;
        } catch (Exception e) {
            e.printStackTrace();
            throw new SSLException("Failed to load certificate for " + hostname, e);
        }
    }
    
    /**
     * 从文件系统加载PKCS证书
     * 
     * @param hostname 主机名
     * @return SSL上下文
     * @throws Exception 加载过程中出现的异常
     */
    private synchronized SslContext loadCertificateFromFile(String hostname) throws Exception {
        File certFile = null;
        String certFilePath = null;
        if(true){
            //String certFilePath = certificatePath + File.separator + hostname + fileSuffix;
            //  创建泛域名证书
            String h1 = certApi.toWildcardDomain(hostname);
            String h2 = h1.substring(2);
            certFilePath = certificatePath+"/"+h2+"/tomcat-ssl.p12";
            certFile = new File(certFilePath);

            // 检查证书文件是否存在 不存在则创建
            if (!certFile.exists()) {
                certApi.wildSsl(h1);
            }
        }else{
            certFilePath = certificatePath+"/"+hostname+"/tomcat-ssl.p12";
            certFile = new File(certFilePath);
            if(!certFile.exists()){
                certApi.singleSsl(hostname);
            }
        }
        
        // 加载PKCS#12密钥库
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        try (FileInputStream fis = new FileInputStream(certFile)) {
            keyStore.load(fis, keystorePassword.toCharArray());
        }
        
        // 获取第一个别名（通常PKCS文件只有一个条目）
        String alias = keyStore.aliases().hasMoreElements() ? keyStore.aliases().nextElement() : null;
        if (alias == null) {
            throw new SSLException("No certificate entry found in " + certFilePath);
        }
        
        // 提取私钥和证书链
        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, keystorePassword.toCharArray());
        Certificate[] certChain = keyStore.getCertificateChain(alias);
        List<X509Certificate> list = new LinkedList<>();
        for (Certificate certificate : certChain) {
            list.add((X509Certificate) certificate);
        }
        if (privateKey == null || certChain == null) {
            throw new SSLException("Failed to extract private key or certificate chain from " + certFilePath);
        }


        // 构建SSL上下文
        return SslContextBuilder.forServer(privateKey, list).build();
    }
    
    /**
     * 获取默认SSL上下文
     * 
     * @return 默认SSL上下文
     * @throws SSLException 无法加载默认证书时抛出
     */
    public SslContext getDefaultSslContext() throws SSLException {
        return loadSslContext("default");
    }
}
